home *** CD-ROM | disk | FTP | other *** search
/ Download Now 8 / Download Now V8.iso / Program / InternetTools / ApacheWebServer1.3.6 / apache_1_3_6_win32.exe / _SETUP.1 / buff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-20  |  39.9 KB  |  1,602 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1996-1999 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer. 
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission. For written permission, please contact
  24.  *    apache@apache.org.
  25.  *
  26.  * 5. Products derived from this software may not be called "Apache"
  27.  *    nor may "Apache" appear in their names without prior written
  28.  *    permission of the Apache Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Group and was originally based
  51.  * on public domain software written at the National Center for
  52.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53.  * For more information on the Apache Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. #include "httpd.h"
  59. #include "http_main.h"
  60. #include "http_log.h"
  61.  
  62. #include <errno.h>
  63. #include <stdio.h>
  64. #include <stdarg.h>
  65. #include <string.h>
  66. #ifndef NO_WRITEV
  67. #include <sys/types.h>
  68. #include <sys/uio.h>
  69. #endif
  70.  
  71. #ifdef HAVE_BSTRING_H
  72. #include <bstring.h>        /* for IRIX, FD_SET calls bzero() */
  73. #endif
  74.  
  75. #ifndef DEFAULT_BUFSIZE
  76. #define DEFAULT_BUFSIZE (4096)
  77. #endif
  78. /* This must be enough to represent (DEFAULT_BUFSIZE - 3) in hex,
  79.  * plus two extra characters.
  80.  */
  81. #ifndef CHUNK_HEADER_SIZE
  82. #define CHUNK_HEADER_SIZE (5)
  83. #endif
  84.  
  85.  
  86. /* bwrite()s of greater than this size can result in a large_write() call,
  87.  * which can result in a writev().  It's a little more work to set up the
  88.  * writev() rather than copy bytes into the buffer, so we don't do it for small
  89.  * writes.  This is especially important when chunking (which is a very likely
  90.  * source of small writes if it's a module using ap_bputc/ap_bputs)...because we
  91.  * have the expense of actually building two chunks for each writev().
  92.  */
  93. #ifndef LARGE_WRITE_THRESHOLD
  94. #define LARGE_WRITE_THRESHOLD 31
  95. #endif
  96.  
  97.  
  98. /*
  99.  * Buffered I/O routines.
  100.  * These are a replacement for the stdio routines.
  101.  * Advantages:
  102.  *  Known semantics for handling of file-descriptors (on close etc.)
  103.  *  No problems reading and writing simultanously to the same descriptor
  104.  *  No limits on the number of open file handles.
  105.  *  Only uses memory resources; no need to ensure the close routine
  106.  *  is called.
  107.  *  Extra code could be inserted between the buffered and un-buffered routines.
  108.  *  Timeouts could be handled by using select or poll before read or write.
  109.  *  Extra error handling could be introduced; e.g.
  110.  *   keep an address to which we should longjump(), or
  111.  *   keep a stack of routines to call on error.
  112.  */
  113.  
  114. /* Notes:
  115.  *  On reading EOF, EOF will set in the flags and no further Input will
  116.  * be done.
  117.  *
  118.  * On an error except for EAGAIN, ERROR will be set in the flags and no
  119.  * futher I/O will be done
  120.  */
  121.  
  122. #ifdef WIN32
  123.  
  124. /*
  125.   select() sometimes returns 1 even though the write will block. We must work around this.
  126. */
  127.  
  128. int sendwithtimeout(int sock, const char *buf, int len, int flags)
  129. {
  130.     int iostate = 1;
  131.     fd_set fdset;
  132.     struct timeval tv;
  133.     int err = WSAEWOULDBLOCK;
  134.     int rv;
  135.     int retry;
  136.  
  137.     if (!(tv.tv_sec = ap_check_alarm()))
  138.     return (send(sock, buf, len, flags));
  139.  
  140.     rv = ioctlsocket(sock, FIONBIO, &iostate);
  141.     iostate = 0;
  142.     if (rv) {
  143.     err = WSAGetLastError();
  144.     ap_assert(0);
  145.     }
  146.     rv = send(sock, buf, len, flags);
  147.     if (rv == SOCKET_ERROR) {
  148.     err = WSAGetLastError();
  149.     if (err == WSAEWOULDBLOCK)
  150.         do {
  151.         retry=0;
  152.  
  153.         FD_ZERO(&fdset);
  154.         FD_SET(sock, &fdset);
  155.         tv.tv_usec = 0;
  156.         rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
  157.         if (rv == SOCKET_ERROR)
  158.             err = WSAGetLastError();
  159.         else if (rv == 0) {
  160.              ioctlsocket(sock, FIONBIO, &iostate);
  161.             if(ap_check_alarm() < 0) {
  162.             WSASetLastError(EINTR);    /* Simulate an alarm() */
  163.             return (SOCKET_ERROR);
  164.             }
  165.         }
  166.         else {
  167.             rv = send(sock, buf, len, flags);
  168.             if (rv == SOCKET_ERROR) {
  169.                 err = WSAGetLastError();
  170.             if(err == WSAEWOULDBLOCK) {
  171.                 ap_log_error(APLOG_MARK,APLOG_DEBUG,NULL,
  172.                 "select claimed we could write, but in fact we couldn't. This is a bug in Windows.");
  173.                 retry=1;
  174.                 Sleep(100);
  175.             }
  176.             }
  177.         }
  178.         } while(retry);
  179.     }
  180.     ioctlsocket(sock, FIONBIO, &iostate);
  181.     if (rv == SOCKET_ERROR)
  182.     WSASetLastError(err);
  183.     return (rv);
  184. }
  185.  
  186.  
  187. int recvwithtimeout(int sock, char *buf, int len, int flags)
  188. {
  189.     int iostate = 1;
  190.     fd_set fdset;
  191.     struct timeval tv;
  192.     int err = WSAEWOULDBLOCK;
  193.     int rv;
  194.  
  195.     if (!(tv.tv_sec = ap_check_alarm()))
  196.     return (recv(sock, buf, len, flags));
  197.  
  198.     rv = ioctlsocket(sock, FIONBIO, &iostate);
  199.     iostate = 0;
  200.     ap_assert(!rv);
  201.     rv = recv(sock, buf, len, flags);
  202.     if (rv == SOCKET_ERROR) {
  203.     err = WSAGetLastError();
  204.     if (err == WSAEWOULDBLOCK) {
  205.         FD_ZERO(&fdset);
  206.         FD_SET(sock, &fdset);
  207.         tv.tv_usec = 0;
  208.         rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
  209.         if (rv == SOCKET_ERROR)
  210.         err = WSAGetLastError();
  211.         else if (rv == 0) {
  212.         ioctlsocket(sock, FIONBIO, &iostate);
  213.         ap_check_alarm();
  214.         WSASetLastError(WSAEWOULDBLOCK);
  215.         return (SOCKET_ERROR);
  216.         }
  217.         else {
  218.         rv = recv(sock, buf, len, flags);
  219.         if (rv == SOCKET_ERROR)
  220.             err = WSAGetLastError();
  221.         }
  222.     }
  223.     }
  224.     ioctlsocket(sock, FIONBIO, &iostate);
  225.     if (rv == SOCKET_ERROR)
  226.     WSASetLastError(err);
  227.     return (rv);
  228. }
  229.  
  230. #endif /* WIN32 */
  231.  
  232.  
  233. /* the lowest level reading primitive */
  234. static int ap_read(BUFF *fb, void *buf, int nbyte)
  235. {
  236.     int rv;
  237.     
  238. #ifdef WIN32
  239.     if (fb->hFH != INVALID_HANDLE_VALUE) {
  240.         if (!ReadFile(fb->hFH,buf,nbyte,&rv,NULL))
  241.             rv = -1;
  242.     }
  243.     else
  244. #endif
  245.     rv = read(fb->fd_in, buf, nbyte);
  246.     
  247.     return rv;
  248. }
  249.  
  250. static ap_inline int buff_read(BUFF *fb, void *buf, int nbyte)
  251. {
  252.     int rv;
  253.  
  254. #if defined (WIN32)
  255.     if (fb->flags & B_SOCKET) {
  256.     rv = recvwithtimeout(fb->fd_in, buf, nbyte, 0);
  257.     if (rv == SOCKET_ERROR)
  258.         errno = WSAGetLastError();
  259.     }
  260.     else
  261.     rv = ap_read(fb, buf, nbyte);
  262. #elif defined(TPF)
  263.     fd_set fds;
  264.     struct timeval tv;
  265.  
  266.     tpf_process_signals();
  267.     if (fb->flags & B_SOCKET) {
  268.         alarm(rv = alarm(0));
  269.         FD_ZERO(&fds);
  270.         FD_SET(fb->fd_in, &fds);
  271.         tv.tv_sec = rv+1;
  272.         tv.tv_usec = 0;
  273.         rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
  274.         if (rv < 1) {
  275.             tpf_process_signals();
  276.             return(rv);
  277.         }
  278.     }
  279.     rv = ap_read(fb, buf, nbyte);
  280. #else
  281.     rv = ap_read(fb, buf, nbyte);
  282. #endif /* WIN32 */
  283.     return rv;
  284. }
  285.  
  286. /* the lowest level writing primitive */
  287. static int ap_write(BUFF *fb, const void *buf, int nbyte)
  288. {
  289.     int rv;
  290.     
  291. #ifdef WIN32
  292.     if (fb->hFH != INVALID_HANDLE_VALUE) {
  293.         if (!WriteFile(fb->hFH,buf,nbyte,&rv,NULL))
  294.           rv = -1;
  295.     }
  296.     else
  297. #endif
  298. #if defined (B_SFIO)
  299.     rv = sfwrite(fb->sf_out, buf, nbyte);
  300. #else
  301.     rv = write(fb->fd, buf, nbyte);
  302. #endif
  303.     
  304.     return rv;
  305. }
  306.  
  307. static ap_inline int buff_write(BUFF *fb, const void *buf, int nbyte)
  308. {
  309.     int rv;
  310.  
  311. #if defined(WIN32)
  312.     if (fb->flags & B_SOCKET) {
  313.     rv = sendwithtimeout(fb->fd, buf, nbyte, 0);
  314.     if (rv == SOCKET_ERROR)
  315.         errno = WSAGetLastError();
  316.     }
  317.     else
  318.     rv = ap_write(fb, buf, nbyte);
  319. #else
  320.     rv = ap_write(fb, buf, nbyte);
  321. #endif /* WIN32 */
  322.     return rv;
  323. }
  324.  
  325. static void doerror(BUFF *fb, int direction)
  326. {
  327.     int errsave = errno;    /* Save errno to prevent overwriting it below */
  328.  
  329.     fb->flags |= (direction == B_RD ? B_RDERR : B_WRERR);
  330.     if (fb->error != NULL)
  331.     (*fb->error) (fb, direction, fb->error_data);
  332.  
  333.     errno = errsave;
  334. }
  335.  
  336. /* Buffering routines */
  337. /*
  338.  * Create a new buffered stream
  339.  */
  340. API_EXPORT(BUFF *) ap_bcreate(pool *p, int flags)
  341. {
  342.     BUFF *fb;
  343.  
  344.     fb = ap_palloc(p, sizeof(BUFF));
  345.     fb->pool = p;
  346.     fb->bufsiz = DEFAULT_BUFSIZE;
  347.     fb->flags = flags & (B_RDWR | B_SOCKET);
  348.  
  349.     if (flags & B_RD)
  350.     fb->inbase = ap_palloc(p, fb->bufsiz);
  351.     else
  352.     fb->inbase = NULL;
  353.  
  354.     /* overallocate so that we can put a chunk trailer of CRLF into this
  355.      * buffer */
  356.     if (flags & B_WR)
  357.     fb->outbase = ap_palloc(p, fb->bufsiz + 2);
  358.     else
  359.     fb->outbase = NULL;
  360.  
  361. #ifdef CHARSET_EBCDIC
  362.     fb->flags |= (flags & B_SOCKET) ? (B_EBCDIC2ASCII | B_ASCII2EBCDIC) : 0;
  363. #endif /*CHARSET_EBCDIC*/
  364.  
  365.     fb->inptr = fb->inbase;
  366.  
  367.     fb->incnt = 0;
  368.     fb->outcnt = 0;
  369.     fb->outchunk = -1;
  370.     fb->error = NULL;
  371.     fb->bytes_sent = 0L;
  372.  
  373.     fb->fd = -1;
  374.     fb->fd_in = -1;
  375. #ifdef WIN32
  376.     fb->hFH = INVALID_HANDLE_VALUE;
  377. #endif
  378.  
  379. #ifdef B_SFIO
  380.     fb->sf_in = NULL;
  381.     fb->sf_out = NULL;
  382.     fb->sf_in = sfnew(fb->sf_in, NIL(Void_t *),
  383.               (size_t) SF_UNBOUND, 0, SF_READ);
  384.     fb->sf_out = sfnew(fb->sf_out, NIL(Void_t *),
  385.                (size_t) SF_UNBOUND, 1, SF_WRITE);
  386. #endif
  387.  
  388.     return fb;
  389. }
  390.  
  391. /*
  392.  * Push some I/O file descriptors onto the stream
  393.  */
  394. API_EXPORT(void) ap_bpushfd(BUFF *fb, int fd_in, int fd_out)
  395. {
  396.     fb->fd = fd_out;
  397.     fb->fd_in = fd_in;
  398. }
  399.  
  400. #ifdef WIN32
  401. /*
  402.  * Push some Win32 handles onto the stream.
  403.  */
  404. API_EXPORT(void) ap_bpushh(BUFF *fb, HANDLE hFH)
  405. {
  406.     fb->hFH = hFH;
  407. }
  408. #endif
  409.  
  410. API_EXPORT(int) ap_bsetopt(BUFF *fb, int optname, const void *optval)
  411. {
  412.     if (optname == BO_BYTECT) {
  413.     fb->bytes_sent = *(const long int *) optval - (long int) fb->outcnt;;
  414.     return 0;
  415.     }
  416.     else {
  417.     errno = EINVAL;
  418.     return -1;
  419.     }
  420. }
  421.  
  422. API_EXPORT(int) ap_bgetopt(BUFF *fb, int optname, void *optval)
  423. {
  424.     if (optname == BO_BYTECT) {
  425.     long int bs = fb->bytes_sent + fb->outcnt;
  426.     if (bs < 0L)
  427.         bs = 0L;
  428.     *(long int *) optval = bs;
  429.     return 0;
  430.     }
  431.     else {
  432.     errno = EINVAL;
  433.     return -1;
  434.     }
  435. }
  436.  
  437. static int bflush_core(BUFF *fb);
  438.  
  439. /*
  440.  * Start chunked encoding.
  441.  *
  442.  * Note that in order for ap_bputc() to be an efficient macro we have to guarantee
  443.  * that start_chunk() has always been called on the buffer before we leave any
  444.  * routine in this file.  Said another way, if a routine here uses end_chunk()
  445.  * and writes something on the wire, then it has to call start_chunk() or set
  446.  * an error condition before returning.
  447.  */
  448. static void start_chunk(BUFF *fb)
  449. {
  450.     if (fb->outchunk != -1) {
  451.     /* already chunking */
  452.     return;
  453.     }
  454.     if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR) {
  455.     /* unbuffered writes */
  456.     return;
  457.     }
  458.  
  459.     /* we need at least the header_len + at least 1 data byte
  460.      * remember that we've overallocated fb->outbase so that we can always
  461.      * fit the two byte CRLF trailer
  462.      */
  463.     if (fb->bufsiz - fb->outcnt < CHUNK_HEADER_SIZE + 1) {
  464.     bflush_core(fb);
  465.     }
  466.     fb->outchunk = fb->outcnt;
  467.     fb->outcnt += CHUNK_HEADER_SIZE;
  468. }
  469.  
  470.  
  471. /*
  472.  * end a chunk -- tweak the chunk_header from start_chunk, and add a trailer
  473.  */
  474. static void end_chunk(BUFF *fb)
  475. {
  476.     int i;
  477.     unsigned char *strp;
  478.  
  479.     if (fb->outchunk == -1) {
  480.     /* not chunking */
  481.     return;
  482.     }
  483.  
  484.     if (fb->outchunk + CHUNK_HEADER_SIZE == fb->outcnt) {
  485.     /* nothing was written into this chunk, and we can't write a 0 size
  486.      * chunk because that signifies EOF, so just erase it
  487.      */
  488.     fb->outcnt = fb->outchunk;
  489.     fb->outchunk = -1;
  490.     return;
  491.     }
  492.  
  493.     /* we know this will fit because of how we wrote it in start_chunk() */
  494.     i = ap_snprintf((char *) &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE,
  495.         "%x", fb->outcnt - fb->outchunk - CHUNK_HEADER_SIZE);
  496.  
  497.     /* we may have to tack some trailing spaces onto the number we just wrote
  498.      * in case it was smaller than our estimated size.  We've also written
  499.      * a \0 into the buffer with ap_snprintf so we might have to put a
  500.      * \r back in.
  501.      */
  502.     strp = &fb->outbase[fb->outchunk + i];
  503.     while (i < CHUNK_HEADER_SIZE - 2) {
  504.     *strp++ = ' ';
  505.     ++i;
  506.     }
  507.     *strp++ = '\015';
  508.     *strp = '\012';
  509. #ifdef CHARSET_EBCDIC
  510.     /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
  511.     ebcdic2ascii(&fb->outbase[fb->outchunk], &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE);
  512. #endif /*CHARSET_EBCDIC*/
  513.  
  514.     /* tack on the trailing CRLF, we've reserved room for this */
  515.     fb->outbase[fb->outcnt++] = '\015';
  516.     fb->outbase[fb->outcnt++] = '\012';
  517.  
  518.     fb->outchunk = -1;
  519. }
  520.  
  521.  
  522. /*
  523.  * Set a flag on (1) or off (0).
  524.  */
  525. API_EXPORT(int) ap_bsetflag(BUFF *fb, int flag, int value)
  526. {
  527.     if (value) {
  528.     fb->flags |= flag;
  529.     if (flag & B_CHUNK) {
  530.         start_chunk(fb);
  531.     }
  532.     }
  533.     else {
  534.     fb->flags &= ~flag;
  535.     if (flag & B_CHUNK) {
  536.         end_chunk(fb);
  537.     }
  538.     }
  539.     return value;
  540. }
  541.  
  542.  
  543. API_EXPORT(int) ap_bnonblock(BUFF *fb, int direction)
  544. {
  545.     int fd;
  546.  
  547.     fd = (direction == B_RD) ? fb->fd_in : fb->fd;
  548. #if defined(O_NONBLOCK)
  549.     return fcntl(fd, F_SETFL, O_NONBLOCK);
  550. #elif defined(O_NDELAY)
  551.     return fcntl(fd, F_SETFL, O_NDELAY);
  552. #elif defined(FNDELAY)
  553.     return fcntl(fd, F_SETFL, FNDELAY);
  554. #else
  555.     /* XXXX: this breaks things, but an alternative isn't obvious...*/
  556.     return 0;
  557. #endif
  558. }
  559.  
  560. API_EXPORT(int) ap_bfileno(BUFF *fb, int direction)
  561. {
  562.     return (direction == B_RD) ? fb->fd_in : fb->fd;
  563. }
  564.  
  565. /*
  566.  * This is called instead of read() everywhere in here.  It implements
  567.  * the B_SAFEREAD functionality -- which is to force a flush() if a read()
  568.  * would block.  It also deals with the EINTR errno result from read().
  569.  * return code is like read() except EINTR is eliminated.
  570.  */
  571.  
  572.  
  573. #if !defined (B_SFIO) || defined (WIN32)
  574. #define saferead saferead_guts
  575. #else
  576. static int saferead(BUFF *fb, char *buf, int nbyte)
  577. {
  578.     return sfread(fb->sf_in, buf, nbyte);
  579. }
  580. #endif
  581.  
  582.  
  583. /* Test the descriptor and flush the output buffer if it looks like
  584.  * we will block on the next read.
  585.  *
  586.  * Note we assume the caller has ensured that fb->fd_in <= FD_SETSIZE
  587.  */
  588. API_EXPORT(void) ap_bhalfduplex(BUFF *fb)
  589. {
  590.     int rv;
  591.     fd_set fds;
  592.     struct timeval tv;
  593.  
  594.     /* We don't need to do anything if the connection has been closed
  595.      * or there is something readable in the incoming buffer
  596.      * or there is nothing flushable in the output buffer.
  597.      */
  598.     if (fb == NULL || fb->fd_in < 0 || fb->incnt > 0 || fb->outcnt == 0) {
  599.     return;
  600.     }
  601.     /* test for a block */
  602.     do {
  603.     FD_ZERO(&fds);
  604.     FD_SET(fb->fd_in, &fds);
  605.     tv.tv_sec = 0;
  606.     tv.tv_usec = 0;
  607.     rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv);
  608.     } while (rv < 0 && errno == EINTR && !(fb->flags & B_EOUT));
  609.  
  610.     /* treat any error as if it would block as well */
  611.     if (rv != 1) {
  612.     ap_bflush(fb);
  613.     }
  614. }
  615.  
  616. static ap_inline int saferead_guts(BUFF *fb, void *buf, int nbyte)
  617. {
  618.     int rv;
  619.  
  620.     if (fb->flags & B_SAFEREAD) {
  621.     ap_bhalfduplex(fb);
  622.     }
  623.     do {
  624.     rv = buff_read(fb, buf, nbyte);
  625.     } while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  626.     return (rv);
  627. }
  628.  
  629. #ifdef B_SFIO
  630. int bsfio_read(Sfio_t * f, char *buf, int nbyte, apache_sfio *disc)
  631. {
  632.     int rv;
  633.     BUFF *fb = disc->buff;
  634.  
  635.     rv = saferead_guts(fb, buf, nbyte);
  636.  
  637.     buf[rv] = '\0';
  638.     f->next = 0;
  639.  
  640.     return (rv);
  641. }
  642.  
  643. int bsfio_write(Sfio_t * f, char *buf, int nbyte, apache_sfio *disc)
  644. {
  645.     return ap_write(disc->buff, buf, nbyte);
  646. }
  647.  
  648. Sfdisc_t *bsfio_new(pool *p, BUFF *b)
  649. {
  650.     apache_sfio *disc;
  651.  
  652.     if (!(disc = (apache_sfio *) ap_palloc(p, sizeof(apache_sfio))))
  653.                 return (Sfdisc_t *) disc;
  654.  
  655.     disc->disc.readf = (Sfread_f) bsfio_read;
  656.     disc->disc.writef = (Sfwrite_f) bsfio_write;
  657.     disc->disc.seekf = (Sfseek_f) NULL;
  658.     disc->disc.exceptf = (Sfexcept_f) NULL;
  659.     disc->buff = b;
  660.  
  661.     return (Sfdisc_t *) disc;
  662. }
  663. #endif
  664.  
  665.  
  666. /* A wrapper around saferead which does error checking and EOF checking
  667.  * yeah, it's confusing, this calls saferead, which calls buff_read...
  668.  * and then there's the SFIO case.  Note that saferead takes care
  669.  * of EINTR.
  670.  */
  671. static int read_with_errors(BUFF *fb, void *buf, int nbyte)
  672. {
  673.     int rv;
  674.  
  675.     rv = saferead(fb, buf, nbyte);
  676.     if (rv == 0) {
  677.     fb->flags |= B_EOF;
  678.     }
  679.     else if (rv == -1 && errno != EAGAIN) {
  680.     doerror(fb, B_RD);
  681.     }
  682.     return rv;
  683. }
  684.  
  685. /*
  686.  * Read up to nbyte bytes into buf.
  687.  * If fewer than byte bytes are currently available, then return those.
  688.  * Returns 0 for EOF, -1 for error.
  689.  * NOTE EBCDIC: The readahead buffer _always_ contains *unconverted* data.
  690.  * Only when the caller retrieves data from the buffer (calls bread)
  691.  * is a conversion done, if the conversion flag is set at that time.
  692.  */
  693. API_EXPORT(int) ap_bread(BUFF *fb, void *buf, int nbyte)
  694. {
  695.     int i, nrd;
  696.  
  697.     if (fb->flags & B_RDERR)
  698.     return -1;
  699.     if (nbyte == 0)
  700.     return 0;
  701.  
  702.     if (!(fb->flags & B_RD)) {
  703.     /* Unbuffered reading.  First check if there was something in the
  704.      * buffer from before we went unbuffered. */
  705.     if (fb->incnt) {
  706.         i = (fb->incnt > nbyte) ? nbyte : fb->incnt;
  707. #ifdef CHARSET_EBCDIC
  708.         if (fb->flags & B_ASCII2EBCDIC)
  709.         ascii2ebcdic(buf, fb->inptr, i);
  710.         else
  711. #endif /*CHARSET_EBCDIC*/
  712.         memcpy(buf, fb->inptr, i);
  713.         fb->incnt -= i;
  714.         fb->inptr += i;
  715.         return i;
  716.     }
  717.     i = read_with_errors(fb, buf, nbyte);
  718. #ifdef CHARSET_EBCDIC
  719.     if (i > 0 && ap_bgetflag(fb, B_ASCII2EBCDIC))
  720.         ascii2ebcdic(buf, buf, i);
  721. #endif /*CHARSET_EBCDIC*/
  722.     return i;
  723.     }
  724.  
  725.     nrd = fb->incnt;
  726. /* can we fill the buffer */
  727.     if (nrd >= nbyte) {
  728. #ifdef CHARSET_EBCDIC
  729.     if (fb->flags & B_ASCII2EBCDIC)
  730.         ascii2ebcdic(buf, fb->inptr, nbyte);
  731.     else
  732. #endif /*CHARSET_EBCDIC*/
  733.     memcpy(buf, fb->inptr, nbyte);
  734.     fb->incnt = nrd - nbyte;
  735.     fb->inptr += nbyte;
  736.     return nbyte;
  737.     }
  738.  
  739.     if (nrd > 0) {
  740. #ifdef CHARSET_EBCDIC
  741.     if (fb->flags & B_ASCII2EBCDIC)
  742.         ascii2ebcdic(buf, fb->inptr, nrd);
  743.     else
  744. #endif /*CHARSET_EBCDIC*/
  745.     memcpy(buf, fb->inptr, nrd);
  746.     nbyte -= nrd;
  747.     buf = nrd + (char *) buf;
  748.     fb->incnt = 0;
  749.     }
  750.     if (fb->flags & B_EOF)
  751.     return nrd;
  752.  
  753. /* do a single read */
  754.     if (nbyte >= fb->bufsiz) {
  755. /* read directly into caller's buffer */
  756.     i = read_with_errors(fb, buf, nbyte);
  757. #ifdef CHARSET_EBCDIC
  758.     if (i > 0 && ap_bgetflag(fb, B_ASCII2EBCDIC))
  759.         ascii2ebcdic(buf, buf, i);
  760. #endif /*CHARSET_EBCDIC*/
  761.     if (i == -1) {
  762.         return nrd ? nrd : -1;
  763.     }
  764.     }
  765.     else {
  766. /* read into hold buffer, then memcpy */
  767.     fb->inptr = fb->inbase;
  768.     i = read_with_errors(fb, fb->inptr, fb->bufsiz);
  769.     if (i == -1) {
  770.         return nrd ? nrd : -1;
  771.     }
  772.     fb->incnt = i;
  773.     if (i > nbyte)
  774.         i = nbyte;
  775. #ifdef CHARSET_EBCDIC
  776.     if (fb->flags & B_ASCII2EBCDIC)
  777.         ascii2ebcdic(buf, fb->inptr, i);
  778.     else
  779. #endif /*CHARSET_EBCDIC*/
  780.     memcpy(buf, fb->inptr, i);
  781.     fb->incnt -= i;
  782.     fb->inptr += i;
  783.     }
  784.     return nrd + i;
  785. }
  786.  
  787.  
  788. /*
  789.  * Reads from the stream into the array pointed to by buff, until
  790.  * a (CR)LF sequence is read, or end-of-file condition is encountered
  791.  * or until n-1 bytes have been stored in buff. If a CRLF sequence is
  792.  * read, it is replaced by a newline character.  The string is then
  793.  * terminated with a null character.
  794.  *
  795.  * Returns the number of bytes stored in buff, or zero on end of
  796.  * transmission, or -1 on an error.
  797.  *
  798.  * Notes:
  799.  *  If null characters are expected in the data stream, then
  800.  * buff should not be treated as a null terminated C string; instead
  801.  * the returned count should be used to determine the length of the
  802.  * string.
  803.  *  CR characters in the byte stream not immediately followed by a LF
  804.  * will be preserved.
  805.  */
  806. API_EXPORT(int) ap_bgets(char *buff, int n, BUFF *fb)
  807. {
  808.     int i, ch, ct;
  809.  
  810. /* Can't do bgets on an unbuffered stream */
  811.     if (!(fb->flags & B_RD)) {
  812.     errno = EINVAL;
  813.     return -1;
  814.     }
  815.     if (fb->flags & B_RDERR)
  816.     return -1;
  817.  
  818.     ct = 0;
  819.     i = 0;
  820.     for (;;) {
  821.     if (i == fb->incnt) {
  822. /* no characters left */
  823.         fb->inptr = fb->inbase;
  824.         fb->incnt = 0;
  825.         if (fb->flags & B_EOF)
  826.         break;
  827.         i = read_with_errors(fb, fb->inptr, fb->bufsiz);
  828.         if (i == -1) {
  829.         buff[ct] = '\0';
  830.         return ct ? ct : -1;
  831.         }
  832.         fb->incnt = i;
  833.         if (i == 0)
  834.         break;        /* EOF */
  835.         i = 0;
  836.         continue;        /* restart with the new data */
  837.     }
  838.  
  839.     ch = fb->inptr[i++];
  840. #ifndef CHARSET_EBCDIC
  841.     if (ch == '\012') {    /* got LF */
  842.         if (ct == 0)
  843.         buff[ct++] = '\n';
  844. /* if just preceeded by CR, replace CR with LF */
  845.         else if (buff[ct - 1] == '\015')
  846.         buff[ct - 1] = '\n';
  847.         else if (ct < n - 1)
  848.         buff[ct++] = '\n';
  849.         else
  850.         i--;        /* no room for LF */
  851.         break;
  852.     }
  853. #else /* an EBCDIC machine: do the same, but convert to EBCDIC on the fly: */
  854.     if (fb->flags & B_ASCII2EBCDIC)
  855.         ch = os_toebcdic[(unsigned char)ch];
  856.     if (ch == os_toebcdic['\012']) {  /* got LF */
  857.         if (ct == 0)
  858.         buff[ct++] = '\n';
  859. /* if just preceeded by CR, replace CR with LF */
  860.         else if (buff[ct - 1] == os_toebcdic['\015'])
  861.         buff[ct - 1] = '\n';
  862.         else if (ct < n - 1)
  863.         buff[ct++] = '\n';
  864.         else
  865.         i--;        /* no room for LF */
  866.         break;
  867.     }
  868. #endif
  869.     if (ct == n - 1) {
  870.         i--;        /* push back ch */
  871.         break;
  872.     }
  873.  
  874.     buff[ct++] = ch;
  875.     }
  876.     fb->incnt -= i;
  877.     fb->inptr += i;
  878.  
  879.     buff[ct] = '\0';
  880.     return ct;
  881. }
  882.  
  883. /*
  884.  * Looks at the stream fb and places the first character into buff
  885.  * without removing it from the stream buffer.
  886.  *
  887.  * Returns 1 on success, zero on end of transmission, or -1 on an error.
  888.  *
  889.  */
  890. API_EXPORT(int) ap_blookc(char *buff, BUFF *fb)
  891. {
  892.     int i;
  893.  
  894.     *buff = '\0';
  895.  
  896.     if (!(fb->flags & B_RD)) {    /* Can't do blookc on an unbuffered stream */
  897.     errno = EINVAL;
  898.     return -1;
  899.     }
  900.     if (fb->flags & B_RDERR)
  901.     return -1;
  902.  
  903.     if (fb->incnt == 0) {    /* no characters left in stream buffer */
  904.     fb->inptr = fb->inbase;
  905.     if (fb->flags & B_EOF)
  906.         return 0;
  907.  
  908.     i = read_with_errors(fb, fb->inptr, fb->bufsiz);
  909.     if (i <= 0) {
  910.         return i;
  911.     }
  912.     fb->incnt = i;
  913.     }
  914.  
  915. #ifndef CHARSET_EBCDIC
  916.     *buff = fb->inptr[0];
  917. #else /*CHARSET_EBCDIC*/
  918.     *buff = (fb->flags & B_ASCII2EBCDIC)
  919.          ? os_toebcdic[(unsigned char)fb->inptr[0]]
  920.          : fb->inptr[0];
  921. #endif /*CHARSET_EBCDIC*/
  922.     return 1;
  923. }
  924.  
  925. /*
  926.  * Skip data until a linefeed character is read
  927.  * Returns 1 on success, 0 if no LF found, or -1 on error
  928.  */
  929. API_EXPORT(int) ap_bskiplf(BUFF *fb)
  930. {
  931.     unsigned char *x;
  932.     int i;
  933.  
  934. /* Can't do bskiplf on an unbuffered stream */
  935.     if (!(fb->flags & B_RD)) {
  936.     errno = EINVAL;
  937.     return -1;
  938.     }
  939.     if (fb->flags & B_RDERR)
  940.     return -1;
  941.  
  942.     for (;;) {
  943.     x = (unsigned char *) memchr(fb->inptr, '\012', fb->incnt);
  944.     if (x != NULL) {
  945.         x++;
  946.         fb->incnt -= x - fb->inptr;
  947.         fb->inptr = x;
  948.         return 1;
  949.     }
  950.  
  951.     fb->inptr = fb->inbase;
  952.     fb->incnt = 0;
  953.     if (fb->flags & B_EOF)
  954.         return 0;
  955.     i = read_with_errors(fb, fb->inptr, fb->bufsiz);
  956.     if (i <= 0)
  957.         return i;
  958.     fb->incnt = i;
  959.     }
  960. }
  961.  
  962. /*
  963.  * output a single character.  Used by ap_bputs when the buffer
  964.  * is full... and so it'll cause the buffer to be flushed first.
  965.  */
  966. API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb)
  967. {
  968.     char ss[1];
  969.  
  970.     ss[0] = c;
  971.     return ap_bwrite(fb, ss, 1);
  972. }
  973.  
  974. /*
  975.  * Fill the buffer and read a character from it
  976.  */
  977. API_EXPORT(int) ap_bfilbuf(BUFF *fb)
  978. {
  979.     int i;
  980.     char buf[1];
  981.  
  982.     i = ap_bread(fb, buf, 1);
  983.     if (i == 0)
  984.     errno = 0;        /* no error; EOF */
  985.     if (i != 1)
  986.     return EOF;
  987.     else
  988.     return buf[0];
  989. }
  990.  
  991.  
  992. /*
  993.  * When doing chunked encodings we really have to write everything in the
  994.  * chunk before proceeding onto anything else.  This routine either writes
  995.  * nbytes and returns 0 or returns -1 indicating a failure.
  996.  *
  997.  * This is *seriously broken* if used on a non-blocking fd.  It will poll.
  998.  *
  999.  * Deals with calling doerror and setting bytes_sent.
  1000.  */
  1001. static int write_it_all(BUFF *fb, const void *buf, int nbyte)
  1002. {
  1003.     int i;
  1004.  
  1005.     if (fb->flags & (B_WRERR | B_EOUT))
  1006.     return -1;
  1007.  
  1008.     while (nbyte > 0) {
  1009.     i = buff_write(fb, buf, nbyte);
  1010.     if (i < 0) {
  1011.         if (errno != EAGAIN && errno != EINTR) {
  1012.         doerror(fb, B_WR);
  1013.         return -1;
  1014.         }
  1015.     }
  1016.     else {
  1017.         nbyte -= i;
  1018.         buf = i + (const char *) buf;
  1019.         fb->bytes_sent += i;
  1020.     }
  1021.     if (fb->flags & B_EOUT)
  1022.         return -1;
  1023.     }
  1024.     return 0;
  1025. }
  1026.  
  1027.  
  1028. #ifndef NO_WRITEV
  1029. /* Similar to previous, but uses writev.  Note that it modifies vec.
  1030.  * return 0 if successful, -1 otherwise.
  1031.  *
  1032.  * Deals with doerror() and bytes_sent.
  1033.  */
  1034. static int writev_it_all(BUFF *fb, struct iovec *vec, int nvec)
  1035. {
  1036.     int i, rv;
  1037.  
  1038.     /* while it's nice an easy to build the vector and crud, it's painful
  1039.      * to deal with a partial writev()
  1040.      */
  1041.     i = 0;
  1042.     while (i < nvec) {
  1043.     do
  1044.         rv = writev(fb->fd, &vec[i], nvec - i);
  1045.     while (rv == -1 && (errno == EINTR || errno == EAGAIN)
  1046.            && !(fb->flags & B_EOUT));
  1047.     if (rv == -1) {
  1048.         if (errno != EINTR && errno != EAGAIN) {
  1049.         doerror(fb, B_WR);
  1050.         }
  1051.         return -1;
  1052.     }
  1053.     fb->bytes_sent += rv;
  1054.     /* recalculate vec to deal with partial writes */
  1055.     while (rv > 0) {
  1056.         if (rv < vec[i].iov_len) {
  1057.         vec[i].iov_base = (char *) vec[i].iov_base + rv;
  1058.         vec[i].iov_len -= rv;
  1059.         rv = 0;
  1060.         }
  1061.         else {
  1062.         rv -= vec[i].iov_len;
  1063.         ++i;
  1064.         }
  1065.     }
  1066.     if (fb->flags & B_EOUT)
  1067.         return -1;
  1068.     }
  1069.     /* if we got here, we wrote it all */
  1070.     return 0;
  1071. }
  1072. #endif
  1073.  
  1074. /* A wrapper for buff_write which deals with error conditions and
  1075.  * bytes_sent.  Also handles non-blocking writes.
  1076.  */
  1077. static int write_with_errors(BUFF *fb, const void *buf, int nbyte)
  1078. {
  1079.     int rv;
  1080.  
  1081.     do
  1082.     rv = buff_write(fb, buf, nbyte);
  1083.     while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
  1084.     if (rv == -1) {
  1085.     if (errno != EAGAIN) {
  1086.         doerror(fb, B_WR);
  1087.     }
  1088.     return -1;
  1089.     }
  1090.     else if (rv == 0) {
  1091.     errno = EAGAIN;
  1092.     return -1;
  1093.     }
  1094.     fb->bytes_sent += rv;
  1095.     return rv;
  1096. }
  1097.  
  1098.  
  1099. /*
  1100.  * A hook to write() that deals with chunking. This is really a protocol-
  1101.  * level issue, but we deal with it here because it's simpler; this is
  1102.  * an interim solution pending a complete rewrite of all this stuff in
  1103.  * 2.0, using something like sfio stacked disciplines or BSD's funopen().
  1104.  *
  1105.  * Can be used on non-blocking descriptors, but only if they're not chunked.
  1106.  * Deals with doerror() and bytes_sent.
  1107.  */
  1108. static int bcwrite(BUFF *fb, const void *buf, int nbyte)
  1109. {
  1110.     char chunksize[16];        /* Big enough for practically anything */
  1111. #ifndef NO_WRITEV
  1112.     struct iovec vec[3];
  1113. #endif
  1114.  
  1115.     if (fb->flags & (B_WRERR | B_EOUT))
  1116.     return -1;
  1117.  
  1118.     if (!(fb->flags & B_CHUNK)) {
  1119.     return write_with_errors(fb, buf, nbyte);
  1120.     }
  1121.  
  1122. #ifdef NO_WRITEV
  1123.     /* without writev() this has poor performance, too bad */
  1124.  
  1125.     ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
  1126. #ifdef CHARSET_EBCDIC
  1127.     /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
  1128.     ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
  1129. #endif /*CHARSET_EBCDIC*/
  1130.     if (write_it_all(fb, chunksize, strlen(chunksize)) == -1)
  1131.     return -1;
  1132.     if (write_it_all(fb, buf, nbyte) == -1)
  1133.     return -1;
  1134.     if (write_it_all(fb, "\015\012", 2) == -1)
  1135.     return -1;
  1136.     return nbyte;
  1137. #else
  1138.     vec[0].iov_base = chunksize;
  1139.     vec[0].iov_len = ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012",
  1140.                  nbyte);
  1141. #ifdef CHARSET_EBCDIC
  1142.     /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
  1143.     ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
  1144. #endif /*CHARSET_EBCDIC*/
  1145.     vec[1].iov_base = (void *) buf;    /* cast is to avoid const warning */
  1146.     vec[1].iov_len = nbyte;
  1147.     vec[2].iov_base = "\015\012";
  1148.     vec[2].iov_len = 2;
  1149.  
  1150.     return writev_it_all(fb, vec, (sizeof(vec) / sizeof(vec[0]))) ? -1 : nbyte;
  1151. #endif
  1152. }
  1153.  
  1154.  
  1155. #ifndef NO_WRITEV
  1156. /*
  1157.  * Used to combine the contents of the fb buffer, and a large buffer
  1158.  * passed in.
  1159.  */
  1160. static int large_write(BUFF *fb, const void *buf, int nbyte)
  1161. {
  1162.     struct iovec vec[4];
  1163.     int nvec;
  1164.     char chunksize[16];
  1165.  
  1166.     /* it's easiest to end the current chunk */
  1167.     if (fb->flags & B_CHUNK) {
  1168.     end_chunk(fb);
  1169.     }
  1170.     nvec = 0;
  1171.     if (fb->outcnt > 0) {
  1172.     vec[nvec].iov_base = (void *) fb->outbase;
  1173.     vec[nvec].iov_len = fb->outcnt;
  1174.     ++nvec;
  1175.     }
  1176.     if (fb->flags & B_CHUNK) {
  1177.     vec[nvec].iov_base = chunksize;
  1178.     vec[nvec].iov_len = ap_snprintf(chunksize, sizeof(chunksize),
  1179.                     "%x\015\012", nbyte);
  1180. #ifdef CHARSET_EBCDIC
  1181.     /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
  1182.     ebcdic2ascii(chunksize, chunksize, strlen(chunksize));
  1183. #endif /*CHARSET_EBCDIC*/
  1184.     ++nvec;
  1185.     vec[nvec].iov_base = (void *) buf;
  1186.     vec[nvec].iov_len = nbyte;
  1187.     ++nvec;
  1188.     vec[nvec].iov_base = "\015\012";
  1189.     vec[nvec].iov_len = 2;
  1190.     ++nvec;
  1191.     }
  1192.     else {
  1193.     vec[nvec].iov_base = (void *) buf;
  1194.     vec[nvec].iov_len = nbyte;
  1195.     ++nvec;
  1196.     }
  1197.  
  1198.     fb->outcnt = 0;
  1199.     if (writev_it_all(fb, vec, nvec)) {
  1200.     return -1;
  1201.     }
  1202.     else if (fb->flags & B_CHUNK) {
  1203.     start_chunk(fb);
  1204.     }
  1205.     return nbyte;
  1206. }
  1207. #endif
  1208.  
  1209.  
  1210. /*
  1211.  * Write nbyte bytes.
  1212.  * Only returns fewer than nbyte if an error ocurred.
  1213.  * Returns -1 if no bytes were written before the error ocurred.
  1214.  * It is worth noting that if an error occurs, the buffer is in an unknown
  1215.  * state.
  1216.  */
  1217. API_EXPORT(int) ap_bwrite(BUFF *fb, const void *buf, int nbyte)
  1218. {
  1219.     int i, nwr, useable_bufsiz;
  1220. #ifdef CHARSET_EBCDIC
  1221.     static char *cbuf = NULL;
  1222.     static int csize = 0;
  1223. #endif /*CHARSET_EBCDIC*/
  1224.  
  1225.     if (fb->flags & (B_WRERR | B_EOUT))
  1226.     return -1;
  1227.     if (nbyte == 0)
  1228.     return 0;
  1229.  
  1230. #ifdef CHARSET_EBCDIC
  1231.     if (ap_bgetflag(fb, B_EBCDIC2ASCII)) {
  1232.         if (nbyte > csize) {
  1233.             if (cbuf != NULL)
  1234.                 free(cbuf);
  1235.             cbuf = malloc(csize = nbyte+HUGE_STRING_LEN);
  1236.             if (cbuf == NULL) {
  1237.                 fprintf(stderr, "Ouch!  Out of memory in ap_bwrite()!\n");
  1238.                 csize = 0;
  1239.             }
  1240.         }
  1241.         ebcdic2ascii((cbuf) ? cbuf : (void*)buf, buf, nbyte);
  1242.         buf = (cbuf) ? cbuf : buf;
  1243.     }
  1244. #endif /*CHARSET_EBCDIC*/
  1245.  
  1246.     if (!(fb->flags & B_WR)) {
  1247. /* unbuffered write -- have to use bcwrite since we aren't taking care
  1248.  * of chunking any other way */
  1249.     return bcwrite(fb, buf, nbyte);
  1250.     }
  1251.  
  1252. #ifndef NO_WRITEV
  1253. /*
  1254.  * Detect case where we're asked to write a large buffer, and combine our
  1255.  * current buffer with it in a single writev().  Note we don't consider
  1256.  * the case nbyte == 1 because modules which use rputc() loops will cause
  1257.  * us to use writev() too frequently.  In those cases we really should just
  1258.  * start a new buffer.
  1259.  */
  1260.     if (fb->outcnt > 0 && nbyte > LARGE_WRITE_THRESHOLD
  1261.     && nbyte + fb->outcnt >= fb->bufsiz) {
  1262.     return large_write(fb, buf, nbyte);
  1263.     }
  1264. #endif
  1265.  
  1266. /*
  1267.  * Whilst there is data in the buffer, keep on adding to it and writing it
  1268.  * out
  1269.  */
  1270.     nwr = 0;
  1271.     while (fb->outcnt > 0) {
  1272. /* can we accept some data? */
  1273.     i = fb->bufsiz - fb->outcnt;
  1274.     if (i > 0) {
  1275.         if (i > nbyte)
  1276.         i = nbyte;
  1277.         memcpy(fb->outbase + fb->outcnt, buf, i);
  1278.         fb->outcnt += i;
  1279.         nbyte -= i;
  1280.         buf = i + (const char *) buf;
  1281.         nwr += i;
  1282.         if (nbyte == 0)
  1283.         return nwr;    /* return if none left */
  1284.     }
  1285.  
  1286. /* the buffer must be full */
  1287.     if (fb->flags & B_CHUNK) {
  1288.         end_chunk(fb);
  1289.         /* it is just too painful to try to re-cram the buffer while
  1290.          * chunking
  1291.          */
  1292.         if (write_it_all(fb, fb->outbase, fb->outcnt) == -1) {
  1293.         /* we cannot continue after a chunked error */
  1294.         return -1;
  1295.         }
  1296.         fb->outcnt = 0;
  1297.         break;
  1298.     }
  1299.     i = write_with_errors(fb, fb->outbase, fb->outcnt);
  1300.     if (i <= 0) {
  1301.         return nwr ? nwr : -1;
  1302.     }
  1303.  
  1304.     /* deal with a partial write */
  1305.     if (i < fb->outcnt) {
  1306.         int j, n = fb->outcnt;
  1307.         unsigned char *x = fb->outbase;
  1308.         for (j = i; j < n; j++)
  1309.         x[j - i] = x[j];
  1310.         fb->outcnt -= i;
  1311.     }
  1312.     else
  1313.         fb->outcnt = 0;
  1314.  
  1315.     if (fb->flags & B_EOUT)
  1316.         return -1;
  1317.     }
  1318. /* we have emptied the file buffer. Now try to write the data from the
  1319.  * original buffer until there is less than bufsiz left.  Note that we
  1320.  * use bcwrite() to do this for us, it will do the chunking so that
  1321.  * we don't have to dink around building a chunk in our own buffer.
  1322.  *
  1323.  * Note also that bcwrite never does a partial write if we're chunking,
  1324.  * so we're guaranteed to either end in an error state, or make it
  1325.  * out of this loop and call start_chunk() below.
  1326.  *
  1327.  * Remember we may not be able to use the entire buffer if we're
  1328.  * chunking.
  1329.  */
  1330.     useable_bufsiz = fb->bufsiz;
  1331.     if (fb->flags & B_CHUNK) useable_bufsiz -= CHUNK_HEADER_SIZE;
  1332.     while (nbyte >= useable_bufsiz) {
  1333.     i = bcwrite(fb, buf, nbyte);
  1334.     if (i <= 0) {
  1335.         return nwr ? nwr : -1;
  1336.     }
  1337.  
  1338.     buf = i + (const char *) buf;
  1339.     nwr += i;
  1340.     nbyte -= i;
  1341.  
  1342.     if (fb->flags & B_EOUT)
  1343.         return -1;
  1344.     }
  1345. /* copy what's left to the file buffer */
  1346.     fb->outcnt = 0;
  1347.     if (fb->flags & B_CHUNK)
  1348.     start_chunk(fb);
  1349.     if (nbyte > 0)
  1350.     memcpy(fb->outbase + fb->outcnt, buf, nbyte);
  1351.     fb->outcnt += nbyte;
  1352.     nwr += nbyte;
  1353.     return nwr;
  1354. }
  1355.  
  1356.  
  1357. static int bflush_core(BUFF *fb)
  1358. {
  1359.     int i;
  1360.  
  1361.     while (fb->outcnt > 0) {
  1362.     i = write_with_errors(fb, fb->outbase, fb->outcnt);
  1363.     if (i <= 0)
  1364.         return -1;
  1365.  
  1366.     /*
  1367.      * We should have written all the data, but if the fd was in a
  1368.      * strange (non-blocking) mode, then we might not have done so.
  1369.      */
  1370.     if (i < fb->outcnt) {
  1371.         int j, n = fb->outcnt;
  1372.         unsigned char *x = fb->outbase;
  1373.         for (j = i; j < n; j++)
  1374.         x[j - i] = x[j];
  1375.     }
  1376.     fb->outcnt -= i;
  1377.  
  1378.     /* If a soft timeout occurs while flushing, the handler should
  1379.      * have set the buffer flag B_EOUT.
  1380.      */
  1381.     if (fb->flags & B_EOUT)
  1382.         return -1;
  1383.     }
  1384.  
  1385.     return 0;
  1386. }
  1387.  
  1388. /*
  1389.  * Flushes the buffered stream.
  1390.  * Returns 0 on success or -1 on error
  1391.  */
  1392. API_EXPORT(int) ap_bflush(BUFF *fb)
  1393. {
  1394.     int ret;
  1395.  
  1396.     if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR)
  1397.     return -1;
  1398.  
  1399.     if (fb->flags & B_CHUNK)
  1400.     end_chunk(fb);
  1401.  
  1402.     ret = bflush_core(fb);
  1403.  
  1404.     if (ret == 0 && (fb->flags & B_CHUNK)) {
  1405.     start_chunk(fb);
  1406.     }
  1407.  
  1408.     return ret;
  1409. }
  1410.  
  1411. /*
  1412.  * Flushes and closes the file, even if an error occurred.
  1413.  * Discards an data that was not read, or not written by bflush()
  1414.  * Sets the EOF flag to indicate no futher data can be read,
  1415.  * and the EOUT flag to indicate no further data can be written.
  1416.  */
  1417. API_EXPORT(int) ap_bclose(BUFF *fb)
  1418. {
  1419.     int rc1, rc2, rc3;
  1420.  
  1421.     if (fb->flags & B_WR)
  1422.     rc1 = ap_bflush(fb);
  1423.     else
  1424.     rc1 = 0;
  1425. #ifdef WIN32
  1426.     if (fb->flags & B_SOCKET) {
  1427.     rc2 = ap_pclosesocket(fb->pool, fb->fd);
  1428.     if (fb->fd_in != fb->fd) {
  1429.         rc3 = ap_pclosesocket(fb->pool, fb->fd_in);
  1430.     }
  1431.     else {
  1432.         rc3 = 0;
  1433.     }
  1434.     }
  1435.     else if (fb->hFH != INVALID_HANDLE_VALUE) {
  1436.         rc2 = ap_pcloseh(fb->pool, fb->hFH);
  1437.         rc3 = 0;
  1438.     }
  1439.     else {
  1440. #endif
  1441.     rc2 = ap_pclosef(fb->pool, fb->fd);
  1442.     if (fb->fd_in != fb->fd) {
  1443.         rc3 = ap_pclosef(fb->pool, fb->fd_in);
  1444.     }
  1445.     else {
  1446.         rc3 = 0;
  1447.     }
  1448. #ifdef WIN32
  1449.     }
  1450. #endif
  1451.  
  1452.     fb->inptr = fb->inbase;
  1453.     fb->incnt = 0;
  1454.     fb->outcnt = 0;
  1455.  
  1456.     fb->flags |= B_EOF | B_EOUT;
  1457.     fb->fd = -1;
  1458.     fb->fd_in = -1;
  1459.  
  1460. #ifdef B_SFIO
  1461.     sfclose(fb->sf_in);
  1462.     sfclose(fb->sf_out);
  1463. #endif
  1464.  
  1465.     if (rc1 != 0)
  1466.     return rc1;
  1467.     else if (rc2 != 0)
  1468.     return rc2;
  1469.     else
  1470.     return rc3;
  1471. }
  1472.  
  1473. /*
  1474.  * returns the number of bytes written or -1 on error
  1475.  */
  1476. API_EXPORT(int) ap_bputs(const char *x, BUFF *fb)
  1477. {
  1478.     int i, j = strlen(x);
  1479.     i = ap_bwrite(fb, x, j);
  1480.     if (i != j)
  1481.     return -1;
  1482.     else
  1483.     return j;
  1484. }
  1485.  
  1486. /*
  1487.  * returns the number of bytes written or -1 on error
  1488.  */
  1489. API_EXPORT_NONSTD(int) ap_bvputs(BUFF *fb,...)
  1490. {
  1491.     int i, j, k;
  1492.     va_list v;
  1493.     const char *x;
  1494.  
  1495.     va_start(v, fb);
  1496.     for (k = 0;;) {
  1497.     x = va_arg(v, const char *);
  1498.     if (x == NULL)
  1499.         break;
  1500.     j = strlen(x);
  1501.     i = ap_bwrite(fb, x, j);
  1502.     if (i != j) {
  1503.         va_end(v);
  1504.         return -1;
  1505.     }
  1506.     k += i;
  1507.     }
  1508.  
  1509.     va_end(v);
  1510.  
  1511.     return k;
  1512. }
  1513.  
  1514. API_EXPORT(void) ap_bonerror(BUFF *fb, void (*error) (BUFF *, int, void *),
  1515.               void *data)
  1516. {
  1517.     fb->error = error;
  1518.     fb->error_data = data;
  1519. }
  1520.  
  1521. struct bprintf_data {
  1522.     ap_vformatter_buff vbuff;
  1523.     BUFF *fb;
  1524. };
  1525.  
  1526. static int bprintf_flush(ap_vformatter_buff *vbuff)
  1527. {
  1528.     struct bprintf_data *b = (struct bprintf_data *)vbuff;
  1529.     BUFF *fb = b->fb;
  1530.  
  1531. #ifdef CHARSET_EBCDIC
  1532.     /* Characters were pushed into the buffer without conversion. Do it now */
  1533.     if (fb->flags & B_EBCDIC2ASCII)
  1534.         ebcdic2ascii(&fb->outbase[fb->outcnt],
  1535.              &fb->outbase[fb->outcnt],
  1536.              b->vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
  1537. #endif /*CHARSET_EBCDIC*/
  1538.     fb->outcnt += b->vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
  1539.     if (fb->outcnt == fb->bufsiz) {
  1540.     if (ap_bflush(fb)) {
  1541.         return -1;
  1542.     }
  1543.     }
  1544.     vbuff->curpos = (char *)&fb->outbase[fb->outcnt];
  1545.     vbuff->endpos = (char *)&fb->outbase[fb->bufsiz];
  1546.     return 0;
  1547. }
  1548.  
  1549. API_EXPORT_NONSTD(int) ap_bprintf(BUFF *fb, const char *fmt, ...)
  1550. {
  1551.     va_list ap;
  1552.     int res;
  1553.     struct bprintf_data b;
  1554.  
  1555.     /* XXX: only works with buffered writes */
  1556.     if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR)
  1557.     return -1;
  1558.     b.vbuff.curpos = (char *)&fb->outbase[fb->outcnt];
  1559.     b.vbuff.endpos = (char *)&fb->outbase[fb->bufsiz];
  1560.     b.fb = fb;
  1561.     va_start(ap, fmt);
  1562.     res = ap_vformatter(bprintf_flush, &b.vbuff, fmt, ap);
  1563.     va_end(ap);
  1564.     if (res != -1) {
  1565. #ifdef CHARSET_EBCDIC
  1566.     /* Characters were pushed into the buffer without conversion. Do it now */
  1567.     if (fb->flags & B_EBCDIC2ASCII)
  1568.         ebcdic2ascii(&fb->outbase[fb->outcnt],
  1569.              &fb->outbase[fb->outcnt],
  1570.              b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
  1571. #endif /*CHARSET_EBCDIC*/
  1572.     fb->outcnt += b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
  1573.     }
  1574.     return res;
  1575. }
  1576.  
  1577. API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list ap)
  1578. {
  1579.     struct bprintf_data b;
  1580.     int res;
  1581.  
  1582.     /* XXX: only works with buffered writes */
  1583.     if ((fb->flags & (B_WRERR | B_EOUT | B_WR)) != B_WR)
  1584.     return -1;
  1585.     b.vbuff.curpos = (char *)&fb->outbase[fb->outcnt];
  1586.     b.vbuff.endpos = (char *)&fb->outbase[fb->bufsiz];
  1587.     b.fb = fb;
  1588.     res = ap_vformatter(bprintf_flush, &b.vbuff, fmt, ap);
  1589.     if (res != -1) {
  1590. #ifdef CHARSET_EBCDIC
  1591.     /* Characters were pushed into the buffer without conversion. Do it now */
  1592.     if (fb->flags & B_EBCDIC2ASCII)
  1593.         ebcdic2ascii(&fb->outbase[fb->outcnt],
  1594.              &fb->outbase[fb->outcnt],
  1595.              b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt]);
  1596. #endif /*CHARSET_EBCDIC*/
  1597.     fb->outcnt += b.vbuff.curpos - (char *)&fb->outbase[fb->outcnt];
  1598.     }
  1599.     return res;
  1600. }
  1601.  
  1602.